<template>
  <div>
    <a-tabs v-model:activeKey="activeKey" type="card">
      <a-tab-pane key="1" tab="短链接管理">
        <a-alert message="安全提示：" type="warning" show-icon style="margin-bottom: 18px">
          <template #description>
            为确保您的原链接安全可跳转，创建短链接之前，请您先报备已通过ICP备案的域名链接（域名格式如：http://www.21ds.cn）。<br />
            支持创建URL及小程序短链接。
          </template>
        </a-alert>
        <div class="table-page-search-wrapper">
          <a-row type="flex" justify="space-between" align="middle">
            <a-col :span="16">
              <a-form layout="inline" :model="listQuery">
                <a-form-item label="搜索项">
                  <a-input v-model:value="listQuery.title" placeholder="输入名称/网址搜索..." />
                </a-form-item>
                <a-form-item>
                  <a-button type="primary" @click="searchSubmit"> 搜索 </a-button>
                </a-form-item>
                <a-form-item>
                  <a-button
                    v-permission="{ action: 'del_short_url_batch' }"
                    type="primary"
                    danger
                    :disabled="selectedRowKeys.length === 0"
                    @click="deleteSelect"
                  >
                    <template #icon>
                      <DeleteOutlined />
                    </template>
                    删除所选
                  </a-button>
                </a-form-item>
                <a-form-item>
                  <a-button
                    v-permission="{ action: 'del_short_url_batch' }"
                    type="link"
                    danger
                    @click="deleteSx"
                  >
                    <template #icon>
                      <DeleteOutlined />
                    </template>
                    清除失效链接
                  </a-button>
                </a-form-item>
              </a-form>
            </a-col>
            <a-col :span="8">
              <div style="margin-right: 0px; float: right; display: flex; align-item: center">
                <a-tooltip placement="top">
                  <template #title>
                    <span>刷新列表</span>
                  </template>
                  <a-button @click="reloadList">
                    <template #icon>
                      <SyncOutlined />
                    </template>
                  </a-button>
                </a-tooltip>
                <a-button
                  v-permission="{ action: 'short_url_add' }"
                  type="primary"
                  style="margin-left: 12px"
                  @click="short_url_add"
                >
                  <template #icon>
                    <PlusOutlined />
                  </template>
                  新增短链接
                </a-button>
              </div>
            </a-col>
          </a-row>
        </div>
        <a-table
          :columns="columns"
          :rowKey="(record) => record._id"
          :dataSource="dataList.data"
          :loading="loading"
          :pagination="pagination"
          :row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
          @change="handleTableChange"
        >
          <template #short="{ text: record }">
            <a :href="'https://21ds.cn/u/' + record" target="_blank" rel="noopener noreferrer"
              >https://21ds.cn/u/{{ record }}</a
            >
            <a-tooltip placement="top">
              <template #title>
                <span>复制短链接</span>
              </template>
              <copy-outlined
                style="margin-left: 6px; font-size: 16px"
                @click="copyData('https://21ds.cn/u/' + record)"
              />
            </a-tooltip>
          </template>
          <template #qrcode="{ text: record }">
            <a-tooltip placement="top">
              <template #title>
                <span>二维活码</span>
              </template>
              <qrcode-outlined
                style="margin-left: 6px; font-size: 16px"
                @click="
                  () => {
                    oauthVisible = true
                    qrcodeData = 'https://21ds.cn/u/' + record
                  }
                "
              />
            </a-tooltip>
          </template>
          <template #url_type="{ text: record }">
            <a-tag v-if="record == 2" color="#07C160">微信小程序</a-tag>
            <a-tag v-else color="blue">URL网址</a-tag>
          </template>
          <template #status="{ text: record }">
            <a-tag v-if="record == 1" color="green">有效</a-tag>
            <a-tag v-else-if="record == 0" color="orange">审核中</a-tag>
            <a-tag v-else color="red">失效</a-tag>
          </template>
          <template #action="{ text: record }">
            <a v-permission="{ action: 'short_url_add' }" @click="short_url_edit(record)">
              <EditOutlined /> 编辑
            </a>
            <a-divider v-permission="{ action: 'short_url_tj' }" type="vertical" />
            <a v-permission="{ action: 'short_url_tj' }" @click="short_url_tj(record)">统计</a>
            <a-divider v-permission="{ action: 'short_url_ext' }" type="vertical" />
            <a
              v-permission="{ action: 'short_url_del' }"
              style="color: red"
              @click="short_url_delete(record)"
            >
              <DeleteOutlined /> 删除
            </a>
          </template>
        </a-table>
      </a-tab-pane>
      <a-tab-pane key="2" tab="链接统计">
        <div class="table-page-search-wrapper">
          <a-row type="flex" justify="space-between" align="middle">
            <a-col :span="12">
              <div>数据更新时间：{{ dataTime }} （不包含今日数据）</div>
            </a-col>
            <a-col :span="12">
              <div style="margin-right: 0px; float: right; display: flex; align-item: center">
                <a-radio-group
                  v-model:value="listQuery.date_num"
                  style="margin-right: 8px"
                  @change="changeDateNum"
                >
                  <a-radio-button :value="-1">昨日</a-radio-button>
                  <a-radio-button :value="7">近7天</a-radio-button>
                  <a-radio-button :value="15">近15天</a-radio-button>
                  <a-radio-button :value="30">近30天</a-radio-button>
                </a-radio-group>
                <a-range-picker v-model:value="listQuery.date_range" @change="changeDate" />
              </div>
            </a-col>
          </a-row>
        </div>
        <div style="background: #ececec; padding: 20px; margin-top: 25px">
          <a-row :gutter="16">
            <a-tooltip placement="top">
              <template #title>
                <span>链接总打开次数</span>
              </template>
              <a-col :span="12">
                <a-card><a-statistic title="打开总次数(PV)" :value="totalData.pv" /></a-card>
              </a-col>
            </a-tooltip>

            <a-tooltip placement="top">
              <template #title>
                <span>打开链接的总用户数，同一用户同一天内多次点击只计1次</span>
              </template>
              <a-col :span="12">
                <a-card><a-statistic title="打开独立用户总数(UV)" :value="totalData.uv" /></a-card>
              </a-col>
            </a-tooltip>
          </a-row>
        </div>
        <div id="all_line" style="margin-top: 20px"></div>
        <a-divider />
        <div style="margin-top: 20px; font-weight: bold">单链接统计</div>
        <div class="table-page-search-wrapper" style="margin-top: 20px">
          <a-row type="flex" justify="space-between" align="middle">
            <a-col :span="12">
              <a-select
                v-model:value="listQuerySingle._id"
                style="width: 320px"
                placeholder="请选择链接"
              >
                <a-select-option
                  v-for="(item, index) in allUrlData"
                  :key="index"
                  :value="item._id"
                  >{{ item.title }}</a-select-option
                >
              </a-select>
            </a-col>
            <a-col :span="12">
              <div style="margin-right: 0px; float: right; display: flex; align-item: center">
                <a-radio-group
                  v-model:value="listQuerySingle.date_num"
                  style="margin-right: 8px"
                  @change="changeDateNumSingle"
                >
                  <a-radio-button :value="0">今日</a-radio-button>
                  <a-radio-button :value="7">近7天</a-radio-button>
                  <a-radio-button :value="15">近15天</a-radio-button>
                  <a-radio-button :value="30">近30天</a-radio-button>
                </a-radio-group>
                <a-range-picker
                  v-model:value="listQuerySingle.date_range"
                  @change="changeDateSingle"
                />
              </div>
            </a-col>
          </a-row>
          <div id="single_line" style="margin-top: 20px"></div>
        </div>
      </a-tab-pane>
    </a-tabs>
    <a-drawer
      width="45%"
      title="短链接详情"
      placement="right"
      :open="drawerShow"
      @close="
        () => {
          drawerShow = false
        }
      "
    >
      <template #extra>
        <a-button
          style="margin-right: 8px"
          @click="
            () => {
              drawerShow = false
            }
          "
          >取消</a-button
        >
        <a-button type="primary" @click="addItem">提交</a-button>
      </template>
      <a-form
        ref="formRef"
        :model="FormState"
        :rules="FormRule"
        :labelCol="labelCol"
        :wrapperCol="wrapperCol"
      >
        <a-form-item label="名称" has-feedback required name="title">
          <a-input v-model:value="FormState.title" placeholder="请输入名称" />
        </a-form-item>
        <a-form-item label="链接类型" has-feedback required name="url_type">
          <a-radio-group v-model:value="FormState.url_type" name="url_type">
            <a-radio :key="1" :value="1">URL网址</a-radio>
            <a-radio :key="2" :value="2">微信小程序</a-radio>
          </a-radio-group>
        </a-form-item>
        <a-form-item v-if="FormState.url_type == 1" required label="源链地址">
          <a-textarea
            v-model:value="FormState.url"
            placeholder="如:（http://www.21ds.cn）"
            autoSize
          />
        </a-form-item>
        <a-form-item v-if="FormState.url_type == 2" required label="选择小程序">
          <a-select
            v-model:value="FormState.ma_id"
            show-search
            placeholder="请选择(支持搜索)"
            :default-active-first-option="false"
            :show-arrow="true"
            :filter-option="false"
            :options="miniAppList"
            :fieldNames="{ value: '_id', label: 'title' }"
            @search="getMiniAppList"
          >
            <template #notFoundContent>
              <a-empty
                image="https://img.alicdn.com/imgextra/i3/573804794/O1CN01IO097G1lHhdtoisyG_!!573804794.png"
                :image-style="{
                  height: '90px'
                }"
              >
                <template #description>
                  <view style="color: rgba(0, 0, 0, 0.88); padding-top: 20px">
                    暂无可选项，请先
                    <router-link :to="{ name: 'miniAppList' }" target="_blank">添加</router-link>
                  </view>
                </template>
              </a-empty>
            </template>
          </a-select>
        </a-form-item>
        <a-form-item v-if="FormState.url_type == 2" required label="页面路径">
          <a-textarea
            v-model:value="FormState.page"
            placeholder="如:/pages/index/index?id=123&name=qianlong"
            autoSize
          />
          <div style="font-size: 12px; margin-top: 8px; color: #6e6e6e">
            注：将小程序转为链接/二维码，适用于短信、邮件、网页、微信等场景打开小程序。长按小程序卡片，将小程序收藏后发送给公众号「龙远科技」可获取appid和路径。
          </div>
        </a-form-item>
        <a-form-item label="有效期" has-feedback required name="expire">
          <a-radio-group v-model:value="FormState.expire" name="expire">
            <a-radio key="99999" value="99999">长期</a-radio>
            <a-radio key="30" value="30">30天</a-radio>
            <a-radio key="60" value="60">60天</a-radio>
            <a-radio key="90" value="90">90天</a-radio>
          </a-radio-group>
        </a-form-item>
      </a-form>
    </a-drawer>
    <a-modal
      v-model:open="oauthVisible"
      title="二维活码"
      :width="500"
      :footer="null"
      @cancel="
        () => {
          oauthVisible = false
        }
      "
    >
      <div style="display: flex; flex-direction: column; align-items: center">
        <qrcode-vue id="qrcode_div" :value="qrcodeData" :size="400" level="H" />
        <a-button style="margin-top: 20px" @click="downQrcode">下载二维活码</a-button>
      </div>
    </a-modal>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs, onMounted, ref, toRaw, watch } from 'vue'
import {
  Row,
  Col,
  Modal,
  Divider,
  Drawer,
  Card,
  Tooltip,
  Statistic,
  RadioGroup,
  RangePicker,
  Tag
} from 'ant-design-vue'
import {
  SyncOutlined,
  PlusOutlined,
  EditOutlined,
  DeleteOutlined,
  ExclamationCircleOutlined,
  DownOutlined,
  QrcodeOutlined,
  CopyOutlined
} from '@ant-design/icons-vue'
import { requestSuccess, requestFailed } from '@/utils/feedback'
import {
  delArtItem,
  getItemList,
  editData,
  allCaptchaData,
  delXSURLBatch,
  getAllUrl,
  delSURLBatch
} from '@/api/short_url'
import { useRouter } from 'vue-router'
import { todayDate, getRangeDate, copyText } from '@/utils/common'
import dayjs, { Dayjs } from 'dayjs'
import { Line } from '@antv/g2plot'
import QrcodeVue from 'qrcode.vue'
import html2canvas from 'html2canvas'
import { getAllItem } from '@/api/miniapp'

export default defineComponent({
  name: 'Captcha',
  components: {
    QrcodeVue,
    SyncOutlined,
    PlusOutlined,
    EditOutlined,
    ExclamationCircleOutlined,
    DownOutlined,
    CopyOutlined,
    QrcodeOutlined,
    DeleteOutlined,
    [Tag.name]: Tag,
    [Row.name]: Row,
    [Card.name]: Card,
    [Tooltip.name]: Tooltip,
    [RadioGroup.name]: RadioGroup,
    [RangePicker.name]: RangePicker,
    [Divider.name]: Divider,
    [Statistic.name]: Statistic,
    [Drawer.name]: Drawer,
    [Col.name]: Col
  },
  setup() {
    const formRef = ref()
    const router = useRouter()
    const dateFormat = 'YYYY-MM-DD'
    const state = reactive<any>({
      loading: true,
      drawerShow: false,
      oauthVisible: false,
      today: todayDate(),
      dataList: [],
      selectedRowKeys: [],
      miniAppList: [],
      selectedKeysPage: {},
      allUrlData: [],
      secretShow: {},
      totalData: {},
      qrcodeData: '',
      allLineRender: '',
      singleLineRender: '',
      dataTime: '',
      allLine: ref(),
      singleLine: ref(),
      activeKey: ref('1'),
      listQuery: {
        pageNo: 1,
        pageSize: 15,
        date_range: [],
        date_range_format: [],
        date_num: -1
      },
      listQuerySingle: {
        _id: '',
        date_range: [],
        date_range_format: [],
        date_num: 0
      },
      pagination: {
        pageSizeOptions: ['15', '30', '50'],
        showSizeChanger: true,
        total: 1,
        showTotal: (total) => `共 ${total} 条数据`,
        pageSize: 15,
        current: 1
      },
      labelCol: {
        xs: { span: 24 },
        sm: { span: 3 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 20 }
      },
      columns: [
        {
          title: '短链接',
          dataIndex: '_id',
          slots: { customRender: 'short' }
        },
        {
          title: '名称',
          dataIndex: 'title'
        },
        {
          title: '二维码',
          dataIndex: '_id',
          slots: { customRender: 'qrcode' }
        },
        {
          title: '链接类型',
          dataIndex: 'url_type',
          slots: { customRender: 'url_type' }
        },
        {
          title: '昨日打开次数(PV)',
          dataIndex: 'yesterday_pv'
        },
        {
          title: '昨日打开独立用户数(UV)',
          dataIndex: 'yesterday_uv'
        },
        {
          title: '状态',
          dataIndex: 'status',
          slots: { customRender: 'status' }
        },
        {
          title: '有效期',
          dataIndex: 'expire_time'
        },
        {
          title: '创建时间',
          dataIndex: 'create_time'
        },
        {
          title: '操作',
          width: '250px',
          slots: { customRender: 'action' }
        }
      ]
    })
    onMounted(() => {
      getDataList()
      getMiniAppList('')
    })

    watch(
      () => state.activeKey,
      () => {
        if (state.activeKey == 1) {
          getDataList()
        } else {
          getRangeDay()
          getAllUrlData()
          getRangeDaySingle('auto')
        }
      }
    )
    watch(
      () => state.listQuerySingle._id,
      () => {
        getRangeDayDataSingle()
      }
    )

    function changeDateNum(e) {
      state.listQuery.date_num = e.target.value
      getRangeDay()
    }
    function downQrcode() {
      let qrHtml = document.getElementById('qrcode_div') as HTMLElement
      html2canvas(qrHtml).then(function (canvas) {
        let base64Img = canvas.toDataURL('image/png')
        const a = document.createElement('a')
        a.href = base64Img
        a.setAttribute('download', state.qrcodeData._id)
        a.click()
      })
    }
    function getMiniAppList(v) {
      getAllItem({ title: v }).then((res) => {
        state.miniAppList = res
      })
    }
    function changeDateNumSingle(e) {
      state.listQuerySingle.date_num = e.target.value
      getRangeDaySingle('click')
    }
    function changeDate(e) {
      state.listQuery.date_range = e
      getRangeDayData()
    }
    function changeDateSingle(e) {
      state.listQuerySingle.date_range = e
      getRangeDayDataSingle()
    }
    function getRangeDaySingle(operate) {
      let end = ''
      let start = ''
      end = getRangeDate(0)
      start = end
      if (state.listQuerySingle.date_num != 0) {
        start = getRangeDate((state.listQuerySingle.date_num - 1) * -1)
      }
      state.listQuerySingle.date_range = ref<[Dayjs, Dayjs]>([
        dayjs(start, dateFormat),
        dayjs(end, dateFormat)
      ])
      if (operate == 'auto') {
        setTimeout(() => {
          getRangeDayDataSingle()
        }, 1000)
      } else {
        getRangeDayDataSingle()
      }
    }
    function getRangeDay() {
      let end = ''
      let start = ''
      end = getRangeDate(-1)
      start = end
      if (state.listQuery.date_num != -1) {
        start = getRangeDate(state.listQuery.date_num * -1)
      }
      state.listQuery.date_range = ref<[Dayjs, Dayjs]>([
        dayjs(start, dateFormat),
        dayjs(end, dateFormat)
      ])
      setTimeout(() => {
        getRangeDayData()
      }, 200)
    }

    function getRangeDayDataSingle() {
      state.listQuerySingle.date_range_format[0] =
        state.listQuerySingle.date_range[0].format(dateFormat)
      state.listQuerySingle.date_range_format[1] =
        state.listQuerySingle.date_range[1].format(dateFormat)
      allCaptchaData(state.listQuerySingle).then((res) => {
        let data = res.data.chart
        if (state.singleLineRender == 'update') {
          state.singleLine.update({
            data
          })
        } else {
          state.singleLine = new Line('single_line', {
            data,
            xField: 'date',
            smooth: true,
            yField: 'value',
            seriesField: 'category',
            yAxis: {
              label: {
                // 数值格式化为千分位
                formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`)
              }
            }
          })
          state.singleLine.render()
          state.singleLineRender = 'update'
        }
      })
    }
    function getRangeDayData() {
      state.listQuery.date_range_format[0] = state.listQuery.date_range[0].format(dateFormat)
      state.listQuery.date_range_format[1] = state.listQuery.date_range[1].format(dateFormat)
      allCaptchaData(state.listQuery).then((res) => {
        state.totalData = res.data.total
        state.dataTime = res.data.date
        let data = res.data.chart
        if (state.allLineRender == 'update') {
          state.allLine.update({
            data
          })
        } else {
          state.allLine = new Line('all_line', {
            data,
            xField: 'date',
            smooth: true,
            yField: 'value',
            seriesField: 'category',
            yAxis: {
              label: {
                // 数值格式化为千分位
                formatter: (v) => `${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`)
              }
            }
          })
          state.allLine.render()
          state.allLineRender = 'update'
        }
      })
    }
    function getAllUrlData() {
      getAllUrl({}).then((res) => {
        if (state.listQuerySingle._id == '') {
          state.listQuerySingle._id = res[0]._id
        }
        state.allUrlData = res
      })
    }

    const FormState = reactive<any>({
      _id: '',
      title: '',
      url: '',
      url_type: 1,
      expire: ''
    })
    const FormRule = {
      title: [{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }],
      expire: [{ required: true, message: '请选择有效期', trigger: ['blur', 'change'] }],
      url: [{ required: true, message: '请输入源链地址', trigger: ['blur', 'change'] }]
    }

    function handleTableChange(e) {
      state.loading = true
      state.pagination.pageSize = e.pageSize
      state.listQuery.pageSize = e.pageSize
      state.listQuery.pageNo = e.current
      state.pagination.current = e.current
      getDataList()
    }

    function reloadList() {
      state.loading = true
      state.listQuery.pageNo = 1
      state.pagination.current = 1
      getDataList()
    }
    function copyData(txt) {
      copyText(txt)
    }

    function searchSubmit() {
      state.loading = true
      state.listQuery.pageNo = 1
      state.pagination.current = 1
      getDataList()
    }
    function short_url_edit(res) {
      for (let item in FormState) {
        FormState[item] = ''
      }
      for (let item in res) {
        FormState[item] = res[item]
      }
      state.drawerShow = true
    }
    function short_url_tj(res) {
      state.listQuerySingle._id = res._id
      getRangeDay()
      getAllUrlData()
      getRangeDaySingle('auto')
      state.activeKey = ref('2')
    }
    function short_url_add() {
      for (let item in FormState) {
        FormState[item] = ''
      }
      state.drawerShow = true
    }

    function getDataList() {
      getItemList(state.listQuery).then((res) => {
        state.loading = false
        state.dataList = res
        state.pagination.total = res.totalCount
      })
    }
    const addItem = () => {
      formRef.value
        .validate()
        .then(() => {
          editData(toRaw(FormState)).then((res) => {
            if (res.code === 200) {
              requestSuccess(res)
              formRef.value.resetFields()
              state.loading = true
              state.drawerShow = false
              reloadList()
            } else {
              requestFailed(res)
            }
          })
        })
        .catch(() => {
          return false
        })
    }
    function short_url_delete(data) {
      Modal.confirm({
        title: '确认删除此链接?',
        content: '【' + data.title + '】',
        okType: 'danger',
        okText: '确认删除',
        onOk() {
          delArtItem({ id: data._id }).then((res) => {
            if (res.code === 200) {
              state.loading = true
              getDataList()
              requestSuccess(res)
            } else {
              requestFailed(res)
            }
          })
        }
      })
    }
    function deleteSelect() {
      Modal.confirm({
        title: '确认批量删除所选内容?',
        okType: 'danger',
        okText: '确认删除',
        onOk() {
          delSURLBatch({ ids: state.selectedRowKeys })
            .then((res) => {
              if (res.code === 200) {
                state.loading = true
                getDataList()
                requestSuccess(res)
              } else {
                requestFailed(res)
              }
            })
            .finally(() => {
              state.selectedRowKeys = []
            })
        }
      })
    }
    function deleteSx() {
      Modal.confirm({
        title: '确认删除全部失效链接?',
        okType: 'danger',
        okText: '确认',
        onOk() {
          delXSURLBatch({})
            .then((res) => {
              if (res.code === 200) {
                state.loading = true
                reloadList()
                requestSuccess(res)
              } else {
                requestFailed(res)
              }
            })
            .finally(() => {
              state.selectedRowKeys = []
            })
        }
      })
    }
    const onSelectChange = (selectedRowKeys) => {
      state.selectedKeysPage[state.listQuery.pageNo] = selectedRowKeys
      let nowList: any[] = []
      for (const key in state.selectedKeysPage) {
        nowList = nowList.concat(state.selectedKeysPage[key])
      }
      const uniqueList = [...new Set(nowList)]
      state.selectedRowKeys = uniqueList
    }
    return {
      ...toRefs(state),
      handleTableChange,
      deleteSelect,
      deleteSx,
      onSelectChange,
      reloadList,
      searchSubmit,
      short_url_delete,
      changeDate,
      changeDateSingle,
      formRef,
      short_url_add,
      changeDateNum,
      copyData,
      changeDateNumSingle,
      FormState,
      short_url_edit,
      short_url_tj,
      getMiniAppList,
      downQrcode,
      addItem,
      FormRule,
      router,
      getDataList
    }
  }
})
</script>

<style scoped></style>
